package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.*;
import cn.wolfcode.car.business.mapper.AppointmentMapper;
import cn.wolfcode.car.business.mapper.BpmnInfoMapper;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.query.CarPackageAuditQuery;
import cn.wolfcode.car.business.service.IBusServiceItemService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class CarPackageAuditServiceImpl implements ICarPackageAuditService {

    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IBusServiceItemService busServiceItemService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;
    @Autowired
    private HistoryService historyService;

    @Override
    public void save(CarPackageAudit carPackageAudit) {
        carPackageAuditMapper.insert(carPackageAudit);
    }

    @Override
    public void update(CarPackageAudit CarPackageAudit) {
        carPackageAuditMapper.updateByPrimaryKey(CarPackageAudit);
    }

    @Override
    public CarPackageAudit get(Long id) {
        return carPackageAuditMapper.selectByPrimaryKey(id);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            carPackageAuditMapper.deleteByPrimaryKey(dictId);
        }
    }

    @Override
    public List<CarPackageAudit> list() {
        return carPackageAuditMapper.selectAll();
    }
    @Override
    public TablePageInfo<CarPackageAudit> query(CarPackageAuditQuery qo) {
//        if (qo.getName()!=null && qo.getName()!="") {
//            qo.setName(qo.getName().substring(0, qo.getName().lastIndexOf(",")));
//        }

        List<CarPackageAudit> carPackageAudits = carPackageAuditMapper.selectForList(qo);
        return new TablePageInfo<CarPackageAudit>(Long.valueOf(carPackageAudits.size()),carPackageAudits);
    }

    @Override
    @Transactional
    public InputStream precessImg(Long id) {
        List high=Collections.EMPTY_LIST;
        List highRow=Collections.EMPTY_LIST;
        String processDefinitionId=null;
        CarPackageAudit audit = this.get(id);
        if (CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(audit.getInstanceId()).singleResult();
            high=runtimeService.getActiveActivityIds(processInstance.getId());
             processDefinitionId = processInstance.getProcessDefinitionId();
        }else {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().finished().processInstanceId(audit.getInstanceId()).singleResult();
            processDefinitionId=historicProcessInstance.getProcessDefinitionId();
        }
        BpmnModel model=repositoryService.getBpmnModel(processDefinitionId);
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        return generator.generateDiagram(model,high,highRow,"宋体","宋体","宋体");
    }

    @Override
    @Transactional
    public void cancelApply(Long id) {
        //合理性校验
        CarPackageAudit audit = this.get(id);
        if (!CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())){
            throw new BusinessException("只有审核中的流程能撤销");
        }

        audit.setStatus(CarPackageAudit.STATUS_CANCEL);
        carPackageAuditMapper.updateByPrimaryKey(audit);
        busServiceItemService.changeStatus(audit.getServiceItemId(),BusServiceItem.AUDITSTATUS_REPLY);
        runtimeService.deleteProcessInstance(audit.getInstanceId(),"流程撤销");
    }

    @Override
    public TablePageInfo<CarPackageAudit> todoQuery(CarPackageAuditQuery qo) {
        BpmnInfo bpmnInfo = bpmnInfoMapper.getByBpmnType(CarPackageAudit.AUDIT_TYPE);
        long count = taskService.createTaskQuery().processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
                .taskAssignee(String.valueOf(ShiroUtils.getUserId())).count();
        if (count==0){
            return new TablePageInfo<>(0L,Collections.EMPTY_LIST);
        }
        List<Task> list = taskService.createTaskQuery().processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
                .taskAssignee(String.valueOf(ShiroUtils.getUserId())).listPage((qo.getPageNum() - 1) * qo.getPageSize(), qo.getPageSize());
        List<String> business=new ArrayList<>();
        for (Task task : list) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            business.add(processInstance.getBusinessKey());
        }
        List<CarPackageAudit> carPackageAudits = carPackageAuditMapper.queryTodoList(business);
        return new TablePageInfo<>(count,carPackageAudits);
    }

    @Override
    public void audit(Long id, Boolean auditStatus, String info) {
        CarPackageAudit audit = this.get(id);
        if (!CarPackageAudit.STATUS_IN_ROGRESS.equals(audit.getStatus())){
            throw new BusinessException("只有进行中的任务才能进行审核");
        }
        String message=ShiroUtils.getUser().getUserName()+(auditStatus?"[:同意]":":拒绝")+info;
        Task task = taskService.createTaskQuery().processInstanceId(audit.getInstanceId()).singleResult();
        taskService.addComment(task.getId(),audit.getInstanceId(),message);
        Map <String,Object> map=new HashMap<>();
        String taskDefinitionKey = task.getTaskDefinitionKey();
        map.put(taskDefinitionKey,auditStatus);
        taskService.complete(task.getId(),map);
            Task nextTask= taskService.createTaskQuery().processInstanceId(audit.getInstanceId()).singleResult();
        if (auditStatus){
            if (nextTask==null){
                    audit.setStatus(CarPackageAudit.STATUS_PASS);
                    carPackageAuditMapper.updateByPrimaryKey(audit);
                    busServiceItemService.changeStatus(audit.getServiceItemId(),BusServiceItem.AUDITSTATUS_APPROVED);
            }
        }else {
                audit.setStatus(CarPackageAudit.STATUS_REJECT);
                carPackageAuditMapper.updateByPrimaryKey(audit);
                busServiceItemService.changeStatus(audit.getServiceItemId(),BusServiceItem.AUDITSTATUS_REPLY);
        }
    }

    @Override
    public TablePageInfo<CarPackageAudit> doneQuery(CarPackageAuditQuery qo) {
        BpmnInfo byBpmnType = bpmnInfoMapper.getByBpmnType(CarPackageAudit.AUDIT_TYPE);
        long count = historyService.createHistoricTaskInstanceQuery().finished().processDefinitionKey(byBpmnType.getProcessDefinitionKey())
                .taskAssignee(String.valueOf(ShiroUtils.getUserId())).count();
        if (count==0){
            return new TablePageInfo<>(0L,Collections.EMPTY_LIST);
        }
        List<String> list=new ArrayList<>();
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().finished().processDefinitionKey(byBpmnType.getProcessDefinitionKey())
                .taskAssignee(String.valueOf(ShiroUtils.getUserId())).listPage((qo.getPageNum()-1)*qo.getPageSize(),qo.getPageSize());
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
            list.add(historicProcessInstance.getBusinessKey());
        }
        List<CarPackageAudit> carPackageAudits = carPackageAuditMapper.queryTodoList(list);
        return new TablePageInfo<>(count,carPackageAudits);
    }

    @Override
    public TablePageInfo<HistoricComment> listHistory(String instanceId) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(instanceId).finished().orderByDeleteReason().desc().list();
        SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd");
        List<HistoricComment> comments=new ArrayList<>();
        for (HistoricTaskInstance task : list) {
            HistoricComment historicComment = new HistoricComment();
            historicComment.setDurationInMillis(String.valueOf(task.getDurationInMillis()));
            historicComment.setEndTime(sm.format(task.getEndTime()));
            historicComment.setStartTime(sm.format(task.getStartTime()));
            historicComment.setTaskName(task.getName());
            List<Comment> taskComments = taskService.getTaskComments(task.getId());
            if (taskComments.size()>0) {
                historicComment.setComment(taskComments.get(0).getFullMessage());
            }
            comments.add(historicComment);
        }
        return new TablePageInfo<>(comments);
    }

}
